﻿#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->progressBar->setValue(0);
    //鼠标双击列表中的目录时，我们进入该目录
    connect(ui->fileList,SIGNAL(itemActivated(QTreeWidgetItem*,int)),
            this,SLOT(processItem(QTreeWidgetItem*,int)));
}

Widget::~Widget()
{
    delete ui;
}

/*****************************************************************************
    我们在“连接”按钮的单击事件槽函数中新建了ftp对象，然后关联了相关的信号和槽。
    这里的listInfo()信号由ftp->list()函数发射，它将在登录命令完成时调用，
    下面我们提到。而dataTransferProgress()信号在数据传输时自动发射。
    最后我们从界面上获得服务器地址，用户名和密码等信息，并以它们为参数执行连接和登录命令。
****************************************************************************/
void Widget::on_connectButton_clicked()   //连接按钮
{
    ui->fileList->clear();
    currentPath.clear();
    isDirectory.clear();

    ftp = new QFtp(this);
    connect(ftp,SIGNAL(commandStarted(int)),
            this,SLOT(ftpCommandStarted(int)));
    connect(ftp,SIGNAL(commandFinished(int,bool)),
            this,SLOT(ftpCommandFinished(int,bool)));
    connect(ftp,SIGNAL(listInfo(QUrlInfo)),
            this,SLOT(addToList(QUrlInfo)));
    connect(ftp,SIGNAL(dataTransferProgress(qint64,qint64)),
            this,SLOT(updateDataTransferProgress(qint64,qint64)));

    QString ftpServer = ui->ftpServerLineEdit->text();
    QString userName = ui->userNameLineEdit->text();
    QString passWord = ui->passWordLineEdit->text();
    ftp->connectToHost(ftpServer,21); //连接到服务器,默认端口号是21
    ftp->login(userName,passWord);   //登录
}

/******************************************************************************************
    每当命令执行时，都会执行ftpCommandStarted()函数，它有一个参数int id，这个id就是调用命令时返回的id，
    如int loginID= ftp->login();这时，我们就可以用if(id == loginID)来判断执行的是否是login()函数。
    但是，我们不想为每个命令都设置一个变量来存储其返回值，所以，我们这里使用了ftp->currentCommand()，
    它也能获取当前执行的命令的类型。在这个函数里我们让开始不同的命令时显示不同的状态信息。
********************************************************************************************/
void Widget::ftpCommandStarted(int)
{
    if(ftp->currentCommand() == QFtp::ConnectToHost){
       ui->label->setText(tr("正在连接到服务器..."));
    }
    if (ftp->currentCommand() == QFtp::Login){
       ui->label->setText(tr("正在登录..."));
    }
    if (ftp->currentCommand() == QFtp::Get){
       ui->label->setText(tr("正在下载..."));
    }
    else if (ftp->currentCommand() == QFtp::Close){
       ui->label->setText(tr("正在关闭连接..."));
    }
}

/********************************************************************
    这个函数它是在一个命令执行结束时执行的。
    它有两个参数，第一个intid，就是调用命令时返回的编号。
    第二个是bool error，它标志现在执行的命令是否出现了错误。
    如果出现了错误，那么error 为true ，否则为false。我们可以利用它来输出错误信息。
    在这个函数中，我们在完成一条命令时显示不同的状态信息，并显示可能的出错信息。
    在if (ftp->currentCommand() == QFtp::Get)中，
    也就是已经完成下载时，我们让textBrowser显示下载的信息。
 **********************************************************************/
void Widget::ftpCommandFinished(int,bool error)
{
    ui->label->setText(tr("登录成功"));
    ftp->list();   //发射listInfo()信号，显示文件列表
    //然后，在下载命令完成时，我们使下载按钮可用，并关闭打开的文件。
    ui->label->setText(tr("已经完成下载"));
    ui->downloadButton->setEnabled(true);
    file->close();
    delete file;
    if (ftp->currentCommand() == QFtp::List){
           if (isDirectory.isEmpty())
           { //如果目录为空,显示“empty”
               ui->fileList->addTopLevelItem(
                      new QTreeWidgetItem(QStringList()<< tr("<empty>")));
               ui->fileList->setEnabled(false);
               ui->label->setText(tr("该目录为空"));
           }
    }
}

/**********************************************************************************************
    当ftp->list()函数执行时会发射listInfo()信号，此时就会执行addToList()函数，
    在这里我们将文件信息显示在Tree Widget上，并在isDirectory中存储该文件的路径及其是否为目录的信息。
    为了使文件与目录进行区分，我们使用了不同的图标file.png和dir.png来表示它们，这两个图标放在了工程文件夹中。
************************************************************************************************/
void Widget::addToList(const QUrlInfo &urlInfo)  //添加文件列表
{
    QTreeWidgetItem *item = new QTreeWidgetItem;
    item->setText(0, urlInfo.name());
    item->setText(1, QString::number(urlInfo.size()));
    item->setText(2, urlInfo.owner());
    item->setText(3, urlInfo.group());
    item->setText(4, urlInfo.lastModified().toString("MMM dd yyyy"));

    QPixmap pixmap(urlInfo.isDir() ? ":/img/1.jpg" : ":/img/2.jpg");
    item->setIcon(0, pixmap);

    isDirectory[urlInfo.name()] = urlInfo.isDir();
    //存储该路径是否为目录的信息
    ui->fileList->addTopLevelItem(item);
    if (!ui->fileList->currentItem()) {
       ui->fileList->setCurrentItem(ui->fileList->topLevelItem(0));
       ui->fileList->setEnabled(true);
    }
}


void Widget::processItem(QTreeWidgetItem* item,int)  //打开一个目录
{
    QString name = item->text(0);
    if (isDirectory.value(name)) {  //如果这个文件是个目录，则打开
       ui->fileList->clear();
       isDirectory.clear();
       currentPath += '/';
       currentPath += name;
       ftp->cd(name);
       ftp->list();
       ui->cdToParentButton->setEnabled(true);
    }
}



void Widget::on_cdToParentButton_clicked()  //返回上级目录按钮
{
    ui->fileList->clear();
    isDirectory.clear();
    currentPath = currentPath.left(currentPath.lastIndexOf('/'));
    if (currentPath.isEmpty()) {
       ui->cdToParentButton->setEnabled(false);
       ftp->cd("/");
    } else {
       ftp->cd(currentPath);
    }
    ftp->list();
}



void Widget::on_downloadButton_clicked()  //下载按钮
{
    QString fileName = ui->fileList->currentItem()->text(0);
    file = new QFile(fileName);
    if (!file->open(QIODevice::WriteOnly))
    {
        delete file;
        return;
    }
    //下载按钮不可用，等下载完成后才可用
    ui->downloadButton->setEnabled(false);    ftp->get(ui->fileList->currentItem()->text(0), file);
}


void Widget::updateDataTransferProgress( //进度条
                  qint64 readBytes,qint64 totalBytes)
{
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(readBytes);
}
